package com.ksyun.campus.metaserver.services;

import com.alibaba.fastjson.JSONObject;
import com.ksyun.campus.metaserver.config.metaserverconfig.MetaServerConfigProperties;
import com.ksyun.campus.metaserver.domain.MetaServerInfo;
import com.ksyun.campus.metaserver.util.MyZkSerializer;
import lombok.extern.slf4j.Slf4j;
import org.I0Itec.zkclient.ZkClient;
import org.apache.logging.log4j.util.Strings;
import org.apache.zookeeper.CreateMode;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.net.InetAddress;
import java.net.UnknownHostException;

@Slf4j
@Component
public class RegistService implements ApplicationRunner {

    @Resource
    private ServletWebServerApplicationContext webServerApplicationContext;
    @Resource
    private MetaServerConfigProperties metaServerConfigProperties;

    @Resource
    private ZkClient zkClient;
    private String nodeName;

    public void registToCenter() {
        InetAddress localHost;
        try {
            localHost = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
        MetaServerInfo dataServerInfo = new MetaServerInfo(localHost.getHostAddress(), String.valueOf(webServerApplicationContext.getWebServer().getPort()),false);
        String rootName = metaServerConfigProperties.getRootName();
        if (!Strings.isNotEmpty(rootName)) {
            throw new RuntimeException("根节点不能为空");
        }
        if (!zkClient.exists(rootName)) {
            zkClient.create(rootName, "root", CreateMode.PERSISTENT);
        }
        nodeName = rootName + metaServerConfigProperties.getNodeName();
        // 重启服务后节点和数据仍存在
        // 解决zk写入数据乱码
        zkClient.setZkSerializer(new MyZkSerializer());
        String node = zkClient.createEphemeralSequential(nodeName, null);
        dataServerInfo.setFileName(metaServerConfigProperties.getDataPath()+node+".recovery");
        String dataServerInfoStr = JSONObject.toJSONString(dataServerInfo);
        dataServerInfoStr = JSONObject.toJSONString(dataServerInfo);

        zkClient.writeData(node, dataServerInfoStr);

        // 将自己添加到本地节点列表中
//        dataServerList.add(nodeName);
        log.debug("node 已添加: {}", nodeName);
        log.debug("metaServerInfo: {}", dataServerInfoStr);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        registToCenter();
    }

    /**
     * 关闭前从zk中移除当前节点
     */
    @PreDestroy
    public void removeFromZkWhenShutdown() {
        zkClient.delete(nodeName);
        zkClient.close();
        log.debug("移除当前节点: {}", nodeName);
    }
}
